home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / mkroom.c < prev    next >
C/C++ Source or Header  |  1993-01-14  |  16KB  |  713 lines

  1. /*    SCCS Id: @(#)mkroom.c    3.1    92/11/14    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * Entry points:
  7.  *    mkroom() -- make and stock a room of a given type
  8.  *    nexttodoor() -- return TRUE if adjacent to a door
  9.  *    has_dnstairs() -- return TRUE if given room has a down staircase
  10.  *    has_upstairs() -- return TRUE if given room has an up staircase
  11.  *    courtmon() -- generate a court monster
  12.  *    save_rooms() -- save rooms into file fd
  13.  *    rest_rooms() -- restore rooms from file fd
  14.  */
  15.  
  16. #include "hack.h"
  17.  
  18. #ifdef OVLB
  19. static boolean FDECL(isbig, (struct mkroom *));
  20. static struct mkroom * FDECL(pick_room,(BOOLEAN_P));
  21. static void NDECL(mkshop), FDECL(mkzoo,(int)), NDECL(mkswamp);
  22. static void NDECL(mktemple);
  23. static coord * FDECL(shrine_pos, (int));
  24. static struct permonst * NDECL(morguemon);
  25. #ifdef ARMY
  26. static struct permonst * NDECL(squadmon);
  27. #endif
  28. static void FDECL(save_room, (int,struct mkroom *));
  29. static void FDECL(rest_room, (int,struct mkroom *));
  30. #endif /* OVLB */
  31.  
  32. #define sq(x) ((x)*(x))
  33.  
  34. extern const struct shclass shtypes[];    /* defined in shknam.c */
  35.  
  36. #ifdef OVLB
  37.  
  38. static boolean
  39. isbig(sroom)
  40. register struct mkroom *sroom;
  41. {
  42.     register int area = (sroom->hx - sroom->lx + 1)
  43.                * (sroom->hy - sroom->ly + 1);
  44.     return( area > 20 );
  45. }
  46.  
  47. void
  48. mkroom(roomtype)
  49. /* make and stock a room of a given type */
  50. int    roomtype;
  51. {
  52.     if (roomtype >= SHOPBASE)
  53.     mkshop();    /* someday, we should be able to specify shop type */
  54.     else switch(roomtype) {
  55.     case COURT:    mkzoo(COURT); break;
  56.     case ZOO:    mkzoo(ZOO); break;
  57.     case BEEHIVE:    mkzoo(BEEHIVE); break;
  58.     case MORGUE:    mkzoo(MORGUE); break;
  59.     case BARRACKS:    mkzoo(BARRACKS); break;
  60.     case SWAMP:    mkswamp(); break;
  61.     case TEMPLE:    mktemple(); break;
  62.     default:    impossible("Tried to make a room of type %d.", roomtype);
  63.     }
  64. }
  65.  
  66. static void
  67. mkshop()
  68. {
  69.     register struct mkroom *sroom;
  70.     int i = -1;
  71. #ifdef WIZARD
  72. # ifdef GCC_WARN
  73.     register char *ep = (char *)0;
  74. # else
  75.     register char *ep;
  76. # endif
  77.  
  78.     /* first determine shoptype */
  79.     if(wizard){
  80.         ep = getenv("SHOPTYPE");
  81.         if(ep){
  82.             if(*ep == 'z' || *ep == 'Z'){
  83.                 mkzoo(ZOO);
  84.                 return;
  85.             }
  86.             if(*ep == 'm' || *ep == 'M'){
  87.                 mkzoo(MORGUE);
  88.                 return;
  89.             }
  90.             if(*ep == 'b' || *ep == 'B'){
  91.                 mkzoo(BEEHIVE);
  92.                 return;
  93.             }
  94.             if(*ep == 't' || *ep == 'T' || *ep == '\\'){
  95.                 mkzoo(COURT);
  96.                 return;
  97.             }
  98. #ifdef ARMY
  99.             if(*ep == 's' || *ep == 'S'){
  100.                 mkzoo(BARRACKS);
  101.                 return;
  102.             }
  103. #endif /* ARMY */
  104.             if(*ep == '_'){
  105.                 mktemple();
  106.                 return;
  107.             }
  108.             if(*ep == '}'){
  109.                 mkswamp();
  110.                 return;
  111.             }
  112.             for(i=0; shtypes[i].name; i++)
  113.                 if(*ep == def_oc_syms[shtypes[i].symb])
  114.                     goto gottype;
  115.             if(*ep == 'g' || *ep == 'G')
  116.                 i = 0;
  117.             else
  118.                 i = -1;
  119.         }
  120.     }
  121. gottype:
  122. #endif
  123.     for(sroom = &rooms[0]; ; sroom++){
  124.         if(sroom->hx < 0) return;
  125.         if(sroom - rooms >= nroom) {
  126.             pline("rooms not closed by -1?");
  127.             return;
  128.         }
  129.         if(sroom->rtype != OROOM) continue;
  130.         if(has_dnstairs(sroom) || has_upstairs(sroom))
  131.             continue;
  132.         if(
  133. #ifdef WIZARD
  134.            (wizard && ep && sroom->doorct != 0) ||
  135. #endif
  136.             sroom->doorct == 1) break;
  137.     }
  138.     if (!sroom->rlit) {
  139.         int x, y;
  140.  
  141.         for(x = sroom->lx - 1; x <= sroom->hx + 1; x++)
  142.         for(y = sroom->ly - 1; y <= sroom->hy + 1; y++)
  143.             levl[x][y].lit = 1;
  144.         sroom->rlit = 1;
  145.     }
  146.  
  147.     if(i < 0) {            /* shoptype not yet determined */
  148.         register int j;
  149.  
  150.         /* pick a shop type at random */
  151.         for (j = rnd(100), i = 0; (j -= shtypes[i].prob) > 0; i++)
  152.         continue;
  153.  
  154.         /* big rooms cannot be wand or book shops,
  155.          * - so make them general stores
  156.          */
  157.         if(isbig(sroom) && (shtypes[i].symb == WAND_CLASS
  158.                 || shtypes[i].symb == SPBOOK_CLASS)) i = 0;
  159.     }
  160.     sroom->rtype = SHOPBASE + i;
  161.  
  162.     /* set room bits before stocking the shop */
  163. #ifdef SPECIALIZATION
  164.     topologize(sroom, FALSE); /* doesn't matter - this is a special room */
  165. #else
  166.     topologize(sroom);
  167. #endif
  168.  
  169.     /* stock the room with a shopkeeper and artifacts */
  170.     stock_room(i, sroom);
  171. }
  172.  
  173. static struct mkroom *
  174. pick_room(strict)
  175. register boolean strict;
  176. /* pick an unused room, preferably with only one door */
  177. {
  178.     register struct mkroom *sroom;
  179.     register int i = nroom;
  180.  
  181.     for(sroom = &rooms[rn2(nroom)]; i--; sroom++) {
  182.         if(sroom == &rooms[nroom])
  183.             sroom = &rooms[0];
  184.         if(sroom->hx < 0)
  185.             return (struct mkroom *)0;
  186.         if(sroom->rtype != OROOM)    continue;
  187.         if(!strict) {
  188.             if(has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3)))
  189.             continue;
  190.         } else if(has_upstairs(sroom) || has_dnstairs(sroom))
  191.             continue;
  192.         if(sroom->doorct == 1 || !rn2(5)
  193. #ifdef WIZARD
  194.                         || wizard
  195. #endif
  196.                             )
  197.             return sroom;
  198.     }
  199.     return (struct mkroom *)0;
  200. }
  201.  
  202. static void
  203. mkzoo(type)
  204. int type;
  205. {
  206.     register struct mkroom *sroom;
  207.  
  208.     if ((sroom = pick_room(FALSE)) != 0) {
  209.         sroom->rtype = type;
  210.         fill_zoo(sroom);
  211.     }
  212. }
  213.  
  214. void
  215. fill_zoo(sroom)
  216. struct mkroom *sroom;
  217. {
  218.     struct monst *mon;
  219.     register int sx,sy,i;
  220.     int sh, tx, ty, goldlim, type = sroom->rtype;
  221.     int rmno = (sroom - rooms) + ROOMOFFSET;
  222.     coord mm;
  223.  
  224. #ifdef GCC_WARN
  225.     tx = ty = goldlim = 0;
  226. #endif
  227.  
  228.     sh = sroom->fdoor;
  229.     switch(type) {
  230.         case COURT:
  231.         if(level.flags.is_maze_lev) {
  232.             for(tx = sroom->lx; tx <= sroom->hx; tx++)
  233.             for(ty = sroom->ly; ty <= sroom->hy; ty++)
  234.                 if(IS_THRONE(levl[tx][ty].typ))
  235.                 goto throne_placed;
  236.         }
  237.         i = 100;
  238.         do {    /* don't place throne on top of stairs */
  239.             (void) somexy(sroom, &mm);
  240.             tx = mm.x; ty = mm.y;
  241.         } while (occupied((xchar)tx, (xchar)ty) && --i > 0);
  242.         throne_placed:
  243.         /* TODO: try to ensure the enthroned monster is an M2_PRINCE */
  244.         break;
  245.         case BEEHIVE:
  246.         tx = sroom->lx + (sroom->hx - sroom->lx + 1)/2;
  247.         ty = sroom->ly + (sroom->hy - sroom->ly + 1)/2;
  248.         if(sroom->irregular) {
  249.             /* center might not be valid, so put queen elsewhere */
  250.             if(levl[tx][ty].roomno != rmno || levl[tx][ty].edge) {
  251.             (void) somexy(sroom, &mm);
  252.             tx = mm.x; ty = mm.y;
  253.             }
  254.         }
  255.         break;
  256.         case ZOO:
  257.         goldlim = 500 * level_difficulty();
  258.         break;
  259.     }
  260.     for(sx = sroom->lx; sx <= sroom->hx; sx++)
  261.         for(sy = sroom->ly; sy <= sroom->hy; sy++) {
  262.         if(sroom->irregular) {
  263.             if(levl[sx][sy].roomno != rmno ||
  264.                levl[sx][sy].edge ||
  265.               (sroom->doorct &&
  266.                distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1))
  267.             continue;
  268.         } else if(!SPACE_POS(levl[sx][sy].typ) ||
  269.               (sroom->doorct &&
  270.                ((sx == sroom->lx && doors[sh].x == sx-1) ||
  271.                 (sx == sroom->hx && doors[sh].x == sx+1) ||
  272.                 (sy == sroom->ly && doors[sh].y == sy-1) ||
  273.                 (sy == sroom->hy && doors[sh].y == sy+1))))
  274.             continue;
  275.         /* don't place monster on explicitly placed throne */
  276.         if(type == COURT && IS_THRONE(levl[sx][sy].typ))
  277.             continue;
  278.         mon = makemon(
  279.             (type == COURT) ? courtmon() :
  280. #ifdef ARMY
  281.             (type == BARRACKS) ? squadmon() :
  282. #endif
  283.             (type == MORGUE) ? morguemon() :
  284.             (type == BEEHIVE) ?
  285.             (sx == tx && sy == ty ? &mons[PM_QUEEN_BEE] : 
  286.              &mons[PM_KILLER_BEE]) :
  287.             (struct permonst *) 0,
  288.            sx, sy);
  289.         if(mon) {
  290.             mon->msleep = 1;
  291.             if (type==COURT && mon->mpeaceful) {
  292.                 mon->mpeaceful = 0;
  293.                 set_malign(mon);
  294.             }
  295.         }
  296.         switch(type) {
  297.             case ZOO:
  298.             if(sroom->doorct)
  299.                 i = sq(dist2(sx,sy,doors[sh].x,doors[sh].y));
  300.             else
  301.                 i = goldlim;
  302.             if(i >= goldlim) i = 5*level_difficulty();
  303.             goldlim -= i;
  304.             mkgold((long) rn1(i, 10), sx, sy);
  305.             break;
  306.             case MORGUE:
  307.             if(!rn2(5))
  308.                 (void) mk_tt_object(CORPSE, sx, sy);
  309.             if(!rn2(10))    /* lots of treasure buried with dead */
  310.                 (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
  311.                          sx, sy, TRUE);
  312.             break;
  313.             case BEEHIVE:
  314.             if(!rn2(3))
  315.                 (void) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy, TRUE);
  316.             break;
  317. #ifdef ARMY
  318.             case BARRACKS:
  319.             if(!rn2(20))    /* the payroll and some loot */
  320.                 (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
  321.                          sx, sy, TRUE);
  322.             break;
  323. #endif
  324.         }
  325.         }
  326.     switch (type) {
  327.           case COURT:
  328.           levl[tx][ty].typ = THRONE;
  329.           (void) somexy(sroom, &mm);
  330.           mkgold((long) rn1(50 * level_difficulty(),10), mm.x, mm.y);
  331.           (void) mksobj_at(CHEST, mm.x, mm.y, TRUE); /* the royal coffers */
  332.           level.flags.has_court = 1;
  333.           break;
  334. #ifdef ARMY
  335.           case BARRACKS:
  336.           level.flags.has_barracks = 1;
  337.           break;
  338. #endif
  339.           case ZOO:
  340.           level.flags.has_zoo = 1;
  341.           break;
  342.           case MORGUE:
  343.           level.flags.has_morgue = 1;
  344.           break;
  345.           case SWAMP:
  346.           level.flags.has_swamp = 1;
  347.           break;
  348.           case BEEHIVE:
  349.           level.flags.has_beehive = 1;
  350.           break;
  351.     }
  352. }
  353.  
  354. void
  355. mkundead(mm)   /* make a swarm of undead around mm */
  356. coord *mm;
  357. {
  358.     register int cnt = (level_difficulty() + 1)/10 + rnd(5);
  359.     register struct permonst *mdat;
  360.  
  361.     while(cnt--) {
  362.           mdat = morguemon();
  363.           if(enexto(mm, mm->x, mm->y, mdat))
  364.            (void) makemon(mdat, mm->x, mm->y);
  365.     }
  366. }
  367.  
  368. static struct permonst *
  369. morguemon()
  370. {
  371.     register int i = rn2(100), hd = rn2(level_difficulty());
  372.  
  373.     if(hd > 10 && i < 10)
  374.         return((Inhell || In_endgame(&u.uz)) ? 
  375.                             mkclass(S_DEMON,0) : &mons[ndemon()]);
  376.     if(hd > 8 && i > 85)
  377.         return(mkclass(S_VAMPIRE,0));
  378.  
  379.     return((i < 20) ? &mons[PM_GHOST]
  380.             : (i < 40) ? &mons[PM_WRAITH] : mkclass(S_ZOMBIE,0));
  381. }
  382.  
  383. static void
  384. mkswamp()    /* Michiel Huisjes & Fred de Wilde */
  385. {
  386.     register struct mkroom *sroom;
  387.     register int sx,sy,i,eelct = 0;
  388.  
  389.     for(i=0; i<5; i++) {        /* 5 tries */
  390.         sroom = &rooms[rn2(nroom)];
  391.         if(sroom->hx < 0 || sroom->rtype != OROOM ||
  392.            has_upstairs(sroom) || has_dnstairs(sroom))
  393.             continue;
  394.  
  395.         /* satisfied; make a swamp */
  396.         sroom->rtype = SWAMP;
  397.         for(sx = sroom->lx; sx <= sroom->hx; sx++)
  398.         for(sy = sroom->ly; sy <= sroom->hy; sy++)
  399.         if(!OBJ_AT(sx, sy) &&
  400.            !MON_AT(sx, sy) && !t_at(sx,sy) && !nexttodoor(sx,sy)) {
  401.             if((sx+sy)%2) {
  402.             levl[sx][sy].typ = POOL;
  403.             if(!eelct || !rn2(4)) {
  404.                 /* mkclass() won't do, as we might get kraken */
  405.                 (void) makemon(rn2(5) ? &mons[PM_GIANT_EEL]
  406.                           : &mons[PM_ELECTRIC_EEL],
  407.                         sx, sy);
  408.                 eelct++;
  409.             }
  410.             } else 
  411.             if(!rn2(4))    /* swamps tend to be moldy */
  412.                 (void) makemon(mkclass(S_FUNGUS,0), sx, sy);
  413.         }
  414.         level.flags.has_swamp = 1;
  415.     }
  416. }
  417.  
  418. static coord *
  419. shrine_pos(roomno)
  420. int roomno;
  421. {
  422.     static coord buf;
  423.     struct mkroom *troom = &rooms[roomno - ROOMOFFSET];
  424.  
  425.     buf.x = troom->lx + ((troom->hx - troom->lx) / 2);
  426.     buf.y = troom->ly + ((troom->hy - troom->ly) / 2);
  427.     return(&buf);
  428. }
  429.  
  430. static void
  431. mktemple()
  432. {
  433.     register struct mkroom *sroom;
  434.     coord *shrine_spot;
  435.     register struct rm *lev;
  436.  
  437.     if(!(sroom = pick_room(TRUE))) return;
  438.  
  439.     /* set up Priest and shrine */
  440.     sroom->rtype = TEMPLE;
  441.     /*
  442.      * In temples, shrines are blessed altars
  443.      * located in the center of the room
  444.      */
  445.     shrine_spot = shrine_pos((sroom - rooms) + ROOMOFFSET);
  446.     lev = &levl[shrine_spot->x][shrine_spot->y];
  447.     lev->typ = ALTAR;
  448.     lev->altarmask = induced_align(80);
  449.     priestini(&u.uz, sroom, shrine_spot->x, shrine_spot->y, FALSE);
  450.      lev->altarmask |= AM_SHRINE;
  451.     level.flags.has_temple = 1;
  452. }
  453.  
  454. boolean
  455. nexttodoor(sx,sy)
  456. register int sx, sy;
  457. {
  458.     register int dx, dy;
  459.     register struct rm *lev;
  460.     for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++) {
  461.         if(!isok(sx+dx, sy+dy)) continue;
  462.         if(IS_DOOR((lev = &levl[sx+dx][sy+dy])->typ) ||
  463.             lev->typ == SDOOR)
  464.             return(TRUE);
  465.     }
  466.     return(FALSE);
  467. }
  468.  
  469. boolean
  470. has_dnstairs(sroom)
  471. register struct mkroom *sroom;
  472. {
  473.     if (sroom == dnstairs_room)
  474.         return TRUE;
  475.     if (sstairs.sx && !sstairs.up)
  476.         return sroom == sstairs_room;
  477.     return FALSE;
  478. }
  479.  
  480. boolean
  481. has_upstairs(sroom)
  482. register struct mkroom *sroom;
  483. {
  484.     if (sroom == upstairs_room)
  485.         return TRUE;
  486.     if (sstairs.sx && sstairs.up)
  487.         return sroom == sstairs_room;
  488.     return FALSE;
  489. }
  490.  
  491. #endif /* OVLB */
  492. #ifdef OVL0
  493.  
  494. int
  495. somex(croom)
  496. register struct mkroom *croom;
  497. {
  498.     return rn2(croom->hx-croom->lx+1) + croom->lx;
  499. }
  500.  
  501. int
  502. somey(croom)
  503. register struct mkroom *croom;
  504. {
  505.     return rn2(croom->hy-croom->ly+1) + croom->ly;
  506. }
  507.  
  508. boolean
  509. inside_room(croom, x, y)
  510. struct mkroom *croom;
  511. xchar x, y;
  512. {
  513.     return (x >= croom->lx-1 && x <= croom->hx+1 &&
  514.         y >= croom->ly-1 && y <= croom->hy+1);
  515. }
  516.  
  517. boolean
  518. somexy(croom, c)
  519. struct mkroom *croom;
  520. coord *c;
  521. {
  522.     int try_cnt = 0;
  523.     int i;
  524.  
  525.     if (croom->irregular) {
  526.         i = (croom - rooms) + ROOMOFFSET;
  527.  
  528.         while(try_cnt++ < 100) {
  529.         c->x = somex(croom);
  530.         c->y = somey(croom);
  531.         if(!levl[c->x][c->y].edge && levl[c->x][c->y].roomno == i)
  532.             return TRUE;
  533.         }
  534.         /* try harder; exhaustively search until one is found */
  535.         for(c->x = croom->lx; c->x <= croom->hx; c->x++)
  536.         for(c->y = croom->ly; c->y <= croom->hy; c->y++)
  537.             if(!levl[c->x][c->y].edge && levl[c->x][c->y].roomno == i)
  538.             return TRUE;
  539.         return FALSE;
  540.     }
  541.  
  542.     if (!croom->nsubrooms) {
  543.         c->x = somex(croom);
  544.         c->y = somey(croom);
  545.         return TRUE;
  546.     }
  547.  
  548.     /* Check that coords doesn't fall into a subroom or into a wall */
  549.  
  550.     while(try_cnt++ < 100) {
  551.         c->x = somex(croom);
  552.         c->y = somey(croom);
  553.         if (IS_WALL(levl[c->x][c->y].typ))
  554.             continue;
  555.         for(i=0 ; i<croom->nsubrooms;i++)
  556.             if(inside_room(croom->sbrooms[i], c->x, c->y))
  557.             goto you_lose;
  558.         break;
  559. you_lose:    ;
  560.     }
  561.     if (try_cnt >= 100)
  562.         return FALSE;
  563.     return TRUE;
  564. }
  565.  
  566. /* 
  567.  * Search for a special room given its type (zoo, court, etc...)
  568.  *     Special values :
  569.  *         - ANY_SHOP
  570.  *         - ANY_TYPE
  571.  */
  572.  
  573. struct mkroom *
  574. search_special(type)
  575. schar type;
  576. {
  577.     register struct mkroom *croom;
  578.  
  579.     for(croom = &rooms[0]; croom->hx >= 0; croom++)
  580.         if((type == ANY_TYPE && croom->rtype != OROOM) ||
  581.            (type == ANY_SHOP && croom->rtype >= SHOPBASE) ||
  582.            croom->rtype == type)
  583.         return croom;
  584.     for(croom = &subrooms[0]; croom->hx >= 0; croom++)
  585.         if((type == ANY_TYPE && croom->rtype != OROOM) ||
  586.            (type == ANY_SHOP && croom->rtype >= SHOPBASE) ||
  587.            croom->rtype == type)
  588.         return croom;
  589.     return (struct mkroom *) 0;
  590. }
  591.  
  592. #endif /* OVL0 */
  593. #ifdef OVLB
  594.  
  595. struct permonst *
  596. courtmon()
  597. {
  598.     int     i = rn2(60) + rn2(3*level_difficulty());
  599.     if (i > 100)        return(mkclass(S_DRAGON,0));
  600.     else if (i > 95)    return(mkclass(S_GIANT,0));
  601.     else if (i > 85)    return(mkclass(S_TROLL,0));
  602.     else if (i > 75)    return(mkclass(S_CENTAUR,0));
  603.     else if (i > 60)    return(mkclass(S_ORC,0));
  604.     else if (i > 45)    return(&mons[PM_BUGBEAR]);
  605.     else if (i > 30)    return(&mons[PM_HOBGOBLIN]);
  606.     else if (i > 15)    return(mkclass(S_GNOME,0));
  607.     else            return(mkclass(S_KOBOLD,0));
  608. }
  609.  
  610. #ifdef ARMY
  611. #define        NSTYPES    (PM_CAPTAIN-PM_SOLDIER+1)
  612.  
  613. static struct {
  614.     unsigned    pm;
  615.     unsigned    prob;
  616. } squadprob[NSTYPES] = {
  617.     {PM_SOLDIER, 80}, {PM_SERGEANT, 15}, {PM_LIEUTENANT, 4}, {PM_CAPTAIN, 1}
  618. };
  619.  
  620. static struct permonst *
  621. squadmon() {        /* return soldier types. */
  622.  
  623.     register struct permonst *ptr;
  624.     register int    i, cpro, sel_prob = rnd(80+level_difficulty());
  625.  
  626.     for(cpro = i = 0; i < NSTYPES; i++)
  627.         if((cpro += squadprob[i].prob) > sel_prob) {
  628.  
  629.         ptr = &mons[squadprob[i].pm];
  630.         goto gotone;
  631.         }
  632.     ptr = &mons[squadprob[rn2(NSTYPES)].pm];
  633. gotone:
  634.     if(!(ptr->geno & (G_GENOD | G_EXTINCT)))  return(ptr);
  635.     else                return((struct permonst *) 0);
  636. }
  637. #endif /* ARMY /* */
  638.  
  639. /* 
  640.  * save_room : A recursive function that saves a room and its subrooms 
  641.  * (if any).
  642.  */
  643.  
  644. static void
  645. save_room(fd, r)
  646. int    fd;
  647. struct mkroom *r;
  648. {
  649.     short i;
  650.     /* 
  651.      * Well, I really should write only useful informations instead
  652.      * of writing the whole structure. That is I should not write
  653.      * the subrooms pointers, but who cares ?
  654.      */
  655.     bwrite(fd, (genericptr_t) r, sizeof(struct mkroom));
  656.     for(i=0; i<r->nsubrooms; i++)
  657.         save_room(fd, r->sbrooms[i]);
  658. }
  659.  
  660. /* 
  661.  * save_rooms : Save all the rooms on disk!
  662.  */
  663.  
  664. void
  665. save_rooms(fd)
  666. int fd;
  667. {
  668.     short i;
  669.  
  670.     /* First, write the number of rooms */
  671.     bwrite(fd, (genericptr_t) &nroom, sizeof(nroom));
  672.     for(i=0; i<nroom; i++)
  673.         save_room(fd, &rooms[i]);
  674. }
  675.  
  676. static void
  677. rest_room(fd, r)
  678. int fd;
  679. struct mkroom *r;
  680. {
  681.     short i;
  682.  
  683.     mread(fd, (genericptr_t) r, sizeof(struct mkroom));
  684.     for(i=0; i<r->nsubrooms; i++) {
  685.         r->sbrooms[i] = &subrooms[nsubroom];
  686.         rest_room(fd, &subrooms[nsubroom++]);
  687.     }
  688. }
  689.  
  690. /* 
  691.  * rest_rooms : That's for restore rooms. Read the rooms structure from
  692.  * the disk.
  693.  */
  694.  
  695. void
  696. rest_rooms(fd)
  697. int    fd;
  698. {
  699.     short i;
  700.  
  701.     mread(fd, (genericptr_t) &nroom, sizeof(nroom));
  702.     nsubroom = 0;
  703.     for(i = 0; i<nroom; i++) {
  704.         rest_room(fd, &rooms[i]);
  705.         rooms[i].resident = (struct monst *)0;
  706.     }
  707.     rooms[nroom].hx = -1;        /* restore ending flags */
  708.     subrooms[nsubroom].hx = -1;
  709. }
  710. #endif /* OVLB */
  711.  
  712. /*mkroom.c*/
  713.